/*******************************************
 * Copyright 2007 Aphrodite Framework for javaME .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * Email : owner@aphroditeme.dev.java.net
 * Contributors:
 *     Kent Elton - initial API and implementation
 *******************************************/

package com.aphrodite.image;

import java.io.IOException;

import javax.microedition.lcdui.Image;

/**
 * Image and color manipulation.
 * <p>
 * The efficiency of alpha processing and rgb data extraction is platform
 * dependent
 * </p>
 * 
 * @author kentelt
 * 
 */
public final class ImageUtil {

	/**
	 * Convert an image into a 2D array of pixels.
	 * 
	 * @param image
	 * @return
	 * @throws NullPointerException
	 *             if the image is null
	 */
	public static final int[][] convertTo2D(Image image) {
		if (image == null) {
			throw new NullPointerException("Image is null");
		}
		int w = image.getWidth();
		int h = image.getHeight();
		int[] argb = getImageRGB(image, w, h);
		int[][] twoD = new int[h][w];
		convertTo2D(argb, w, h, twoD);
		return twoD;
	}

	/**
	 * 
	 * @param argb
	 *            data
	 * @param srcWidth
	 *            argb image width
	 * @param srcHeight
	 *            argb image height
	 * @param dest
	 *            the converted array int[argb.getHeight()][argb.getWidth()];
	 */
	public static final void convertTo2D(int[] argb, int srcWidth, int srcHeight, int[][] dest) {
		for (int i = 0; i < srcHeight; i++) {
			for (int j = 0; j < srcWidth; j++) {
				dest[i][j] = argb[i * srcWidth + j];
			}
		}
	}

	/**
	 * used to extract an image from another image
	 * 
	 * @param source
	 *            the source image
	 * @param x
	 *            X coordinate for extraction
	 * @param y
	 *            Y coordinate for extraction
	 * @param width
	 *            width of the image to be extracted
	 * @param height
	 *            height of the image to be extracted
	 * @return Image object
	 * @throws IllegalArgumentException
	 *             if the x/y values are greater than the image height
	 */
	public static final Image extractImage(Image source, int x, int y, int width, int height) {
		if (x > width || y > height) {
			throw new IllegalArgumentException("x/y is greater than image height");
		}
		Image result = Image.createImage(width, height);
		result.getGraphics().drawImage(source, -x, -y, 0);
		return result;
	}

	public static int getA(int color) {
		return ((color & 0xff000000) >> 24);
	}

	public static final byte getAlphaComponent(int ARGB) {
		int alpha = ARGB & 0xff000000;
		return (byte) (alpha >> 24);
	}

	/**
	 * Get the blue component of a hexadecimal color value
	 * 
	 * @param color
	 * @return int
	 */
	public static byte getBlueComponent(int ARGB) {
		return com.aphrodite.util.NumericConverter.toSignedByte((byte) (ARGB & 0xff));
	}

	/**
	 * Get the green component of a hexadecimal color value
	 * 
	 * @param color
	 * @return int
	 */
	public static byte getGreenComponent(int ARGB) {
		return com.aphrodite.util.NumericConverter.toSignedByte((byte) ((ARGB >> 8) & 0xff));
	}

	public static final Image getImage(String name) {
		Image image = null;
		try {
			image = Image.createImage(name);
		} catch (IOException e) {
			System.out.println("[AppUtils] could not load image " + name);
		}
		return image;
	}

	public static final int[] getImageRGB(Image image, int width, int height) {
		int[] imageData = new int[width * height];
		image.getRGB(imageData, 0, width, 0, 0, width, height);
		return imageData;
	}

	/**
	 * Get the red component of a hexadecimal color value
	 * 
	 * @param color
	 * @return int
	 */

	public static byte getRedComponent(int ARGB) {
		return com.aphrodite.util.NumericConverter.toSignedByte((byte) ((ARGB >> 16) & 0xff));
	}

	/**
	 * 
	 * @param image
	 * @param thumbNailWidth
	 *            The width of the Thumbnail. The height is determined
	 *            proportionally.
	 * @return Thumbnail image
	 */
	public static Image getThumbnail(Image image, int thumbNailWidth) {
		int sourceWidth = image.getWidth();
		int sourceHeight = image.getHeight();

		int thumbWidth = thumbNailWidth;
		int thumbHeight = -1;

		if (thumbHeight == -1)
			thumbHeight = thumbWidth * sourceHeight / sourceWidth;

		Image thumb = Image.createImage(thumbWidth, thumbHeight);
		javax.microedition.lcdui.Graphics g = thumb.getGraphics();

		for (int y = 0; y < thumbHeight; y++) {
			for (int x = 0; x < thumbWidth; x++) {
				g.setClip(x, y, 1, 1);
				int dx = x * sourceWidth / thumbWidth;
				int dy = y * sourceHeight / thumbHeight;
				g.drawImage(image, x - dx, y - dy, javax.microedition.lcdui.Graphics.LEFT
						| javax.microedition.lcdui.Graphics.TOP);
			}
		}

		Image immutableThumb = Image.createImage(thumb);

		return immutableThumb;
	}

	/**
	 * Creates a array of images from a horizontal image strip
	 * 
	 * @param image
	 *            the image strip
	 * @param number
	 *            number of images to be extracted
	 * @param width
	 *            width of each image (should be identical)
	 * @param height
	 *            height of each image (should be identical)
	 * @return
	 */
	public static final Image[] getTiles(Image image, final int number, final int width, final int height) {
		Image[] img = new Image[number];
		for (int i = 0; i < number; i++) {
			img[i] = Image.createImage(image, i * width, 0, width, height, 0);
		}
		return img;
	}

	/**
	 * Get the pixels from an image with given dims
	 * 
	 * @param img
	 * @param x
	 *            point in the image
	 * @param y
	 *            point in the image
	 * @param width
	 *            of the grab area
	 * @param height
	 *            of the grab area
	 * @throws IllegalArgumentException
	 *             if <code>x</code> is greater than <code>img</code> width or
	 *             <code>y> is greater than<code> img</code> height.
	 * @return
	 */
	public static final int[] grabPixels(Image img, int x, int y, int width, int height) {
		if (x > img.getWidth() || y > img.getHeight()) {
			throw new IllegalArgumentException();
		}
		int[] pixels = new int[width * height];
		img.getRGB(pixels, 0, width, x, y, width, height);
		return pixels;
	}

	private ImageUtil() {

	}
}
